package com.koko.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.koko.admin.dto.*;
import com.koko.admin.entity.Admin;
import com.koko.admin.vo.AdminDetailVO;
import com.koko.admin.vo.AdminLoginVO;
import com.koko.admin.vo.AdminVO;
import com.koko.constant.JwtClaimsConstant;
import com.koko.context.BaseContext;
import com.koko.properties.JwtAdminProperties;
import com.koko.result.PageResult;
import com.koko.result.Result;
import com.koko.service.AdminService;
import com.koko.utils.Base64Util;
import com.koko.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/admin")
public class AdminController {
    @Autowired
    private AdminService adminService;
    @Autowired
    private JwtAdminProperties jwtAdminProperties;
    @Value("${koko.path.image}")
    private String basePath;

    /**
     * 管理员登录
     * @param adminLoginDTO
     * @return
     */
    @PostMapping("/login")
    public Result<AdminLoginVO> login(@RequestBody AdminLoginDTO adminLoginDTO) {
        log.info("管理员登录：{}", adminLoginDTO);

        Admin admin = adminService.login(adminLoginDTO);

        // 登录成功，生成jwt令牌
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.ADMIN_ID, admin.getId());
        claims.put(JwtClaimsConstant.ADMIN_PERMISSION, admin.getStatus());
        String token = JwtUtil.createJWT(
                jwtAdminProperties.getAdminSecretKey(),
                jwtAdminProperties.getAdminTtl(),
                claims);

        AdminVO adminInfo = AdminVO.builder()
                .id(admin.getId())
                .name(admin.getName())
                .username(admin.getUsername())
                .phone(admin.getPhone())
                .idNumber(admin.getIdNumber())
                .avatar(Base64Util.convertImageToBase64(basePath + admin.getAvatar()))
                .status(admin.getStatus())
                .build();

        AdminLoginVO adminLoginVO = AdminLoginVO.builder()
                .adminInfo(adminInfo)
                .token(token)
                .build();

        return Result.success(adminLoginVO);
    }

    /**
     * 获取登录的管理员信息（通过token）
     * @return
     */
    @GetMapping("/admininfo")
    public Result<AdminVO> getAdminInfo() {
        log.info("获取管理员信息");
        Long adminId = BaseContext.getCurrentId();
        Admin admin = adminService.getAdminInfo(adminId);
        AdminVO adminVO = AdminVO.builder()
                .id(admin.getId())
                .name(admin.getName())
                .username(admin.getUsername())
                .phone(admin.getPhone())
                .idNumber(admin.getIdNumber())
                .avatar(Base64Util.convertImageToBase64(basePath + admin.getAvatar()))
                .status(admin.getStatus())
                .build();
        return Result.success(adminVO);
    }

    /**
     * 更新管理员信息
     * @return
     */
    @PutMapping("/admininfo")
    @CacheEvict(value = "adminCache", key = "'adminDetail' + '_' + #adminDTO.id")
    public Result<String> updateAdminInfo(@RequestBody AdminDTO adminDTO) {
        log.info("更新管理员信息");
        adminService.updateAdminInfo(adminDTO);
        return Result.success();
    }

    /**
     * 更新管理员密码
     * @param passwordUpdateDTO
     * @return
     */
    @PatchMapping("/password")
    public Result<String> updatePassword(@RequestBody PasswordUpdateDTO passwordUpdateDTO) {
        log.info("更新密码");
        adminService.updatePassword(passwordUpdateDTO);
        return Result.success();
    }

    /**
     * 更新管理员头像
     * @param adminDTO
     * @return
     */
    @PatchMapping("/avatar")
    @CacheEvict(value = "adminCache", key = "'adminDetail' + '_' + #adminDTO.id")
    public Result<String> updateAvatar(@RequestBody AdminDTO adminDTO) {
        log.info("更新头像");
        // 1. 拼接文件名
        String base64Avatar = adminDTO.getAvatar();
        String fileName = Base64Util.getFileName(base64Avatar);
        // 2. 更新头像
        adminService.updateAvatar(fileName, BaseContext.getCurrentId());
        // 3. 写入文件夹
        String fullPath = basePath + fileName;
        Base64Util.convertBase64ToImage(base64Avatar, fullPath);
        return Result.success();
    }

    /**
     * 管理员分页查询
     * @param pageParamsDTO
     * @return
     */
    @GetMapping("/page")
    @Cacheable(value = "adminCache", key = "'adminPage'")
    public Result<PageResult> adminList(PageParamsDTO pageParamsDTO) {
        log.info("查询管理员分页数据");
        // 1. 获取分页内容
        Page<Admin> adminPage = adminService.pageQuery(pageParamsDTO);
        // 2. 拷贝分页中的列表
        List<Admin> adminList = adminPage.getRecords();
        List<AdminVO> adminVOList = adminList.stream().map((item) ->{
            AdminVO adminVO = new AdminVO();
            BeanUtils.copyProperties(item, adminVO, "avatar");
            adminVO.setId(item.getId());
            return adminVO;
        }).collect(Collectors.toList());
        // 3. 封装分页结果
        PageResult<AdminVO> pageResult = new PageResult<>();
        pageResult.setTotal(adminPage.getTotal());
        pageResult.setRecords(adminVOList);
        return Result.success(pageResult);
    }

    /**
     * 管理员详细数据
     * @param id
     * @return
     */
    @GetMapping("/detail/{id}")
    @Cacheable(value = "adminCache", key = "'adminDetail' + '_' + #id")
    public Result<AdminDetailVO> getAdminDetail(@PathVariable Long id) {
        log.info("查询管理员详情");
        Admin admin = adminService.getAdminInfo(id);
        String createUser = adminService.getAdminInfo(admin.getCreateUser()).getUsername();
        String updateUser = adminService.getAdminInfo(admin.getUpdateUser()).getUsername();
        AdminDetailVO adminDetailVO = new AdminDetailVO();
        BeanUtils.copyProperties(admin, adminDetailVO);
        adminDetailVO.setId(admin.getId());
        adminDetailVO.setCreateTime(admin.getCreateTime());
        adminDetailVO.setUpdateTime(admin.getUpdateTime());
        adminDetailVO.setCreateUser(createUser);
        adminDetailVO.setUpdateUser(updateUser);
        adminDetailVO.setAvatar(Base64Util.convertImageToBase64(basePath + admin.getAvatar()));
        return Result.success(adminDetailVO);
    }

    /**
     * 更新管理员状态
     * @param adminDTO
     * @return
     */
    @PatchMapping("/state")
    @CacheEvict(value = "adminCache", key = "'adminDetail' + '_' + #adminDTO.id")
    public Result<String> changeAdminState(@RequestBody AdminDTO adminDTO) {
        log.info("切换管理员状态");
        adminService.changeState(adminDTO.getId());
        return Result.success();
    }

    /**
     * 更新管理员
     * @param adminDTO
     * @return
     */
    @PutMapping("")
    @CacheEvict(value = "adminCache", key = "'adminDetail' + '_' + #adminDTO.id")
    public Result<String> updateAdmin(@RequestBody AdminDTO adminDTO) {
        log.info("更新管理员");
        // 如果图片为空
        if (adminDTO.getAvatar() == null) {
            adminService.updateAdmin(adminDTO);
            return Result.success();
        }
        // 1. 判断传过来的图片对象和数据库中是否相等
        Admin admin = adminService.getAdminInfo(adminDTO.getId());
        String avatarData = Base64Util.convertImageToBase64(basePath + admin.getAvatar());
        // 2. 相等，不跟新头像
        if (adminDTO.getAvatar().equals(avatarData)) {
            adminDTO.setAvatar(null);
            adminService.updateAdmin(adminDTO);
            return Result.success();
        }
        // 3. 不相等，更新头像
        // 3.1. 拼接文件名
        String base64Avatar = adminDTO.getAvatar();
        String fileName = Base64Util.getFileName(base64Avatar);
        // 3.2. 更新数据
        adminDTO.setAvatar(fileName);
        adminService.updateAdmin(adminDTO);
        // 3.3. 写入文件夹
        String fullPath = basePath + fileName;
        Base64Util.convertBase64ToImage(base64Avatar, fullPath);
        return Result.success();
    }

    /**
     * 添加管理员
     * @param adminDTO
     * @return
     */
    @PostMapping("")
    @CacheEvict(value = "adminCache", allEntries = true)
    public Result<String> addAdmin(@RequestBody AdminDTO adminDTO) {
        log.info("添加管理员");
        // 1. 如果图片为空
        if (adminDTO.getAvatar() == null) {
            adminDTO.setAvatar("");
            adminService.addAdmin(adminDTO);
            return Result.success();
        }
        String base64Avatar = adminDTO.getAvatar();
        String fileName = Base64Util.getFileName(base64Avatar);
        // 2. 照片不为空
        // 2.1. 添加图片路径
        adminDTO.setAvatar(fileName);
        adminService.addAdmin(adminDTO);
        // 2.3. 写入文件夹
        String fullPath = basePath + fileName;
        Base64Util.convertBase64ToImage(base64Avatar, fullPath);
        return Result.success();
    }

    @GetMapping("/name/{id}")
    public Result<String> getAdminName(@PathVariable Long id) {
        Admin admin = adminService.getAdminInfo(id);
        return Result.success(admin.getName());
    }
}
